library("tmap")
Warning message:
In scan(file = file, what = what, sep = sep, quote = quote, dec = dec,  :
  EOF within quoted string
library("tmaptools")
library("sf")
library("leaflet")
library("scales")
library("htmlwidgets")
library("htmltools")
setwd(getwd())
 # This file contains candidate votes by county from the 2016 election.
primary <- read.csv("2016_election.csv")
# This file contains party information. Only 2016 results will be used. 
data <- read.csv("elections.csv") 
e2016 <- subset(data, select = c("county","fips_code", "total_2016", "dem_2016", "gop_2016", "oth_2016"))
# This shapefile will be used in building maps. 
usshapefile <- "cb_2014_us_county_5m/cb_2014_us_county_5m.shp" 
usgeo <- read_shape(file = usshapefile, as.sf = TRUE)
Z-dimension discarded

Data Trimming

# Renaming for ease.
colnames(usgeo)[5] <- "fips_code" 
colnames(usgeo)[6] <- "county" 
# Vote data did not contain U.S. territories.
usgeo <- usgeo[which(as.numeric(as.character(usgeo$fips_code)) <= 60000),] 
# Removes leading zeroes from FIPS codes. 
usgeo$fips_code <- gsub("(^|[^0-9])0+", "\\1", usgeo$fips_code, perl = TRUE) 
usgeo$fips_code <- as.integer(usgeo$fips_code) 
# These are by party.
e2016$dem_vote_pct <- e2016$dem_2016 / e2016$total_2016
e2016$gop_vote_pct <- e2016$gop_2016 / e2016$total_2016
e2016$oth_vote_pct <- e2016$oth_2016 / e2016$total_2016
# Adding new column for the party winner of every county. 
e2016 <- transform(e2016, winner = ifelse(e2016$dem_2016 > e2016$gop_2016 & e2016$dem_2016 > e2016$oth_2016, "Dem",
                                   ifelse(e2016$gop_2016 > e2016$oth_2016 & e2016$gop_2016 > e2016$dem_2016, "GOP", "Other"))) 
# For some reason the election data did not contain Alaska, so we remove it (Alaska FIPS start with 2).
usgeo <- usgeo[which(as.numeric(as.character(usgeo$STATEFP)) != 02),]
usgeo <- usgeo[which(as.numeric(as.character(usgeo$fips_code)) != 15005),]
# Ensuring order between the FIPS columns so they merge.
usgeo <- usgeo[order(usgeo$fips_code),]
e2016 <- e2016[order(e2016$fips_code),]
# This is a precautionary renaming to make sure the append goes smoothly.
names(usgeo)[5] <- "fips"
usmap <- append_data(usgeo, e2016, key.shp = "fips", key.data = "fips_code")
Keys match perfectly.
# Note: In 2016_election.csv, I edited the names of counties to remove "county" from the end of every county. I also removed "parish" and "city."
# Important: Carson City, Nevada, Charles City, VA, and James City, VA all need to keep "city"" in their name.
# Dona Ana is messed up, run this in console once to fix it: usmap["1576", "county"] = "Dona Ana"
# dt is a data frame to organize Donald Trump's data. There is probably a cleaner way to do this. Will come back later.
dt <- subset(primary, cand == "Donald Trump")
dt <- subset(dt, !is.na(county))
dt$fips <- as.integer(as.character(dt$fips))
dt <- dt[order(as.integer(as.character(dt$fips))),]
# Same thing as above but with Hillary.
hc <- subset(primary, cand == "Hillary Clinton")
hc <- subset(hc, !is.na(county))
hc$fips <- as.integer(as.character(hc$fips))
hc <-hc[order(as.integer(as.character(hc$fips))),]
names(dt)[6] <- "trump_votes"
names(dt)[9] <- "trump_pct"
df <- subset(dt, select = c("county", "fips", "trump_votes", "trump_pct"))
names(hc)[6] <- "hillary_votes"
names(hc)[9] <- "hillary_pct"
df$hillary_votes <- hc$hillary_votes
df$hillary_pct <- hc$hillary_pct
df$total_votes <- hc$total_votes
df$trump_margin <- df$trump_votes - df$hillary_votes
# Adds winner column to data frame.
df <- transform(df, pres_winner = ifelse(df$hillary_pct > df$trump_pct, "Clinton", "Trump"))
usmap <- append_data(usmap, df, key.shp = "fips", key.data = "fips")
Keys match perfectly.

Map Creation

# Finding the mix and max keep color scaling fair between candidates.
min <- min(c(usmap$trump_pct, usmap$hillary_pct))
max <- max(c(usmap$trump_pct, usmap$hillary_pct))
# Creating color palettes
gop_palette <- colorNumeric(palette = "Blues", domain=c(min, max))
dem_palette <- colorNumeric(palette = "Reds", domain = c(min, max))
winner_palette <- colorFactor(c("Blue","Red" ), domain = usmap$pres_winner)
# Pop-up window for when you click on a county.
uspopup <- paste("County: ", usmap$county, "<br>",
"Winner: ", usmap$pres_winner, "<br>",
"Trump: ", percent(usmap$trump_pct), "<br>",
"Clinton: ", percent(usmap$hillary_pct), "<br>",
"Margin: ", usmap$trump_margin, " votes.")
usmap <- sf::st_transform(usmap, "+proj=longlat +datum=WGS84")
# Building the map!
widget <- leaflet(usmap) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(stroke = TRUE,
              weight = 1,
              smoothFactor = 0.2,
              fillOpacity = .75,
              popup = uspopup,
              color = ~winner_palette(usmap$pres_winner),
              group ="Winners"
 ) %>%
    addLegend(position = "bottomleft", colors = c("#3333FF", "#CD3700"), labels = c("Clinton", "Trump")) %>%
  addPolygons(stroke = TRUE,
       weight = 1,
       smoothFactor = 0.2, 
       fillOpacity = .75, 
       popup = uspopup, 
       color = ~dem_palette(usmap$trump_pct),
       group ="Trump"
      ) %>%
  addPolygons(stroke = TRUE,
              weight = 1,
              smoothFactor = 0.2, 
              fillOpacity = .75, 
              popup = uspopup, 
              color = ~gop_palette(usmap$hillary_pct),
              group = "Clinton"
  ) %>%
  
  addLayersControl(
      baseGroups=c("Winners", "Trump", "Clinton"), # "College degs" "Other"
      position = "bottomleft",
      options = layersControlOptions(collapsed = FALSE)
      ) 
widget
#saveWidget(widget, file = "election_map.html")
# This will eventually show a gradient across counties using marginal votes. 
#testPalette <- colorRampPalette(c("Blue","White","Red" ))
# palData <- classIntervals(usmap$trump_margin, style="quantile")
# usmap$colors <- findColours(palData, winnerPalette(100))
# 
# leaflet(usmap) %>%
#   addProviderTiles("CartoDB.Positron") %>%
#   addPolygons(stroke=TRUE,
#               weight=1,
#               smoothFactor = 0.2,
#               fillOpacity = .75,
#               popup = uspopup,
#               color = ~colors,
#               group ="Winners"
#  ) %>%
#     addLegend(position="bottomleft", colors=c("#3333FF", "#CD3700"), labels=c("Clinton", "Trump"))
LS0tCnRpdGxlOiAiMjAxNiBFbGVjdGlvbiBFeHBsb3JhdG9yeSBBbmFseXNpcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoInRtYXAiKQpsaWJyYXJ5KCJ0bWFwdG9vbHMiKQpsaWJyYXJ5KCJzZiIpCmxpYnJhcnkoImxlYWZsZXQiKQpsaWJyYXJ5KCJzY2FsZXMiKQpsaWJyYXJ5KCJodG1sd2lkZ2V0cyIpCmxpYnJhcnkoImh0bWx0b29scyIpCnNldHdkKGdldHdkKCkpCmBgYAoKYGBge3J9CiAjIFRoaXMgZmlsZSBjb250YWlucyBjYW5kaWRhdGUgdm90ZXMgYnkgY291bnR5IGZyb20gdGhlIDIwMTYgZWxlY3Rpb24uCnByaW1hcnkgPC0gcmVhZC5jc3YoIjIwMTZfZWxlY3Rpb24uY3N2IikKCiMgVGhpcyBmaWxlIGNvbnRhaW5zIHBhcnR5IGluZm9ybWF0aW9uLiBPbmx5IDIwMTYgcmVzdWx0cyB3aWxsIGJlIHVzZWQuIApkYXRhIDwtIHJlYWQuY3N2KCJlbGVjdGlvbnMuY3N2IikgCmUyMDE2IDwtIHN1YnNldChkYXRhLCBzZWxlY3QgPSBjKCJjb3VudHkiLCJmaXBzX2NvZGUiLCAidG90YWxfMjAxNiIsICJkZW1fMjAxNiIsICJnb3BfMjAxNiIsICJvdGhfMjAxNiIpKQoKIyBUaGlzIHNoYXBlZmlsZSB3aWxsIGJlIHVzZWQgaW4gYnVpbGRpbmcgbWFwcy4gCnVzc2hhcGVmaWxlIDwtICJjYl8yMDE0X3VzX2NvdW50eV81bS9jYl8yMDE0X3VzX2NvdW50eV81bS5zaHAiIAp1c2dlbyA8LSByZWFkX3NoYXBlKGZpbGUgPSB1c3NoYXBlZmlsZSwgYXMuc2YgPSBUUlVFKQpgYGAKCiNEYXRhIFRyaW1taW5nCmBgYHtyfQojIFJlbmFtaW5nIGZvciBlYXNlLgpjb2xuYW1lcyh1c2dlbylbNV0gPC0gImZpcHNfY29kZSIgCmNvbG5hbWVzKHVzZ2VvKVs2XSA8LSAiY291bnR5IiAKCiMgVm90ZSBkYXRhIGRpZCBub3QgY29udGFpbiBVLlMuIHRlcnJpdG9yaWVzLgp1c2dlbyA8LSB1c2dlb1t3aGljaChhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih1c2dlbyRmaXBzX2NvZGUpKSA8PSA2MDAwMCksXSAKCiMgUmVtb3ZlcyBsZWFkaW5nIHplcm9lcyBmcm9tIEZJUFMgY29kZXMuIAp1c2dlbyRmaXBzX2NvZGUgPC0gZ3N1YigiKF58W14wLTldKTArIiwgIlxcMSIsIHVzZ2VvJGZpcHNfY29kZSwgcGVybCA9IFRSVUUpIAp1c2dlbyRmaXBzX2NvZGUgPC0gYXMuaW50ZWdlcih1c2dlbyRmaXBzX2NvZGUpIAoKIyBUaGVzZSBhcmUgYnkgcGFydHkuCmUyMDE2JGRlbV92b3RlX3BjdCA8LSBlMjAxNiRkZW1fMjAxNiAvIGUyMDE2JHRvdGFsXzIwMTYKZTIwMTYkZ29wX3ZvdGVfcGN0IDwtIGUyMDE2JGdvcF8yMDE2IC8gZTIwMTYkdG90YWxfMjAxNgplMjAxNiRvdGhfdm90ZV9wY3QgPC0gZTIwMTYkb3RoXzIwMTYgLyBlMjAxNiR0b3RhbF8yMDE2CgojIEFkZGluZyBuZXcgY29sdW1uIGZvciB0aGUgcGFydHkgd2lubmVyIG9mIGV2ZXJ5IGNvdW50eS4gCmUyMDE2IDwtIHRyYW5zZm9ybShlMjAxNiwgd2lubmVyID0gaWZlbHNlKGUyMDE2JGRlbV8yMDE2ID4gZTIwMTYkZ29wXzIwMTYgJiBlMjAxNiRkZW1fMjAxNiA+IGUyMDE2JG90aF8yMDE2LCAiRGVtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZTIwMTYkZ29wXzIwMTYgPiBlMjAxNiRvdGhfMjAxNiAmIGUyMDE2JGdvcF8yMDE2ID4gZTIwMTYkZGVtXzIwMTYsICJHT1AiLCAiT3RoZXIiKSkpIAoKIyBGb3Igc29tZSByZWFzb24gdGhlIGVsZWN0aW9uIGRhdGEgZGlkIG5vdCBjb250YWluIEFsYXNrYSwgc28gd2UgcmVtb3ZlIGl0IChBbGFza2EgRklQUyBzdGFydCB3aXRoIDIpLgp1c2dlbyA8LSB1c2dlb1t3aGljaChhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih1c2dlbyRTVEFURUZQKSkgIT0gMDIpLF0KdXNnZW8gPC0gdXNnZW9bd2hpY2goYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIodXNnZW8kZmlwc19jb2RlKSkgIT0gMTUwMDUpLF0KCiMgRW5zdXJpbmcgb3JkZXIgYmV0d2VlbiB0aGUgRklQUyBjb2x1bW5zIHNvIHRoZXkgbWVyZ2UuCnVzZ2VvIDwtIHVzZ2VvW29yZGVyKHVzZ2VvJGZpcHNfY29kZSksXQplMjAxNiA8LSBlMjAxNltvcmRlcihlMjAxNiRmaXBzX2NvZGUpLF0KCiMgVGhpcyBpcyBhIHByZWNhdXRpb25hcnkgcmVuYW1pbmcgdG8gbWFrZSBzdXJlIHRoZSBhcHBlbmQgZ29lcyBzbW9vdGhseS4KbmFtZXModXNnZW8pWzVdIDwtICJmaXBzIgp1c21hcCA8LSBhcHBlbmRfZGF0YSh1c2dlbywgZTIwMTYsIGtleS5zaHAgPSAiZmlwcyIsIGtleS5kYXRhID0gImZpcHNfY29kZSIpCmBgYAoKCmBgYHtyfQojIE5vdGU6IEluIDIwMTZfZWxlY3Rpb24uY3N2LCBJIGVkaXRlZCB0aGUgbmFtZXMgb2YgY291bnRpZXMgdG8gcmVtb3ZlICJjb3VudHkiIGZyb20gdGhlIGVuZCBvZiBldmVyeSBjb3VudHkuIEkgYWxzbyByZW1vdmVkICJwYXJpc2giIGFuZCAiY2l0eS4iCiMgSW1wb3J0YW50OiBDYXJzb24gQ2l0eSwgTmV2YWRhLCBDaGFybGVzIENpdHksIFZBLCBhbmQgSmFtZXMgQ2l0eSwgVkEgYWxsIG5lZWQgdG8ga2VlcCAiY2l0eSIiIGluIHRoZWlyIG5hbWUuCiMgRG9uYSBBbmEgaXMgbWVzc2VkIHVwLCBydW4gdGhpcyBpbiBjb25zb2xlIG9uY2UgdG8gZml4IGl0OiB1c21hcFsiMTU3NiIsICJjb3VudHkiXSA9ICJEb25hIEFuYSIKCiMgZHQgaXMgYSBkYXRhIGZyYW1lIHRvIG9yZ2FuaXplIERvbmFsZCBUcnVtcCdzIGRhdGEuIFRoZXJlIGlzIHByb2JhYmx5IGEgY2xlYW5lciB3YXkgdG8gZG8gdGhpcy4gV2lsbCBjb21lIGJhY2sgbGF0ZXIuCmR0IDwtIHN1YnNldChwcmltYXJ5LCBjYW5kID09ICJEb25hbGQgVHJ1bXAiKQpkdCA8LSBzdWJzZXQoZHQsICFpcy5uYShjb3VudHkpKQpkdCRmaXBzIDwtIGFzLmludGVnZXIoYXMuY2hhcmFjdGVyKGR0JGZpcHMpKQpkdCA8LSBkdFtvcmRlcihhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihkdCRmaXBzKSkpLF0KCiMgU2FtZSB0aGluZyBhcyBhYm92ZSBidXQgd2l0aCBIaWxsYXJ5LgpoYyA8LSBzdWJzZXQocHJpbWFyeSwgY2FuZCA9PSAiSGlsbGFyeSBDbGludG9uIikKaGMgPC0gc3Vic2V0KGhjLCAhaXMubmEoY291bnR5KSkKaGMkZmlwcyA8LSBhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihoYyRmaXBzKSkKaGMgPC1oY1tvcmRlcihhcy5pbnRlZ2VyKGFzLmNoYXJhY3RlcihoYyRmaXBzKSkpLF0KCm5hbWVzKGR0KVs2XSA8LSAidHJ1bXBfdm90ZXMiCm5hbWVzKGR0KVs5XSA8LSAidHJ1bXBfcGN0IgpkZiA8LSBzdWJzZXQoZHQsIHNlbGVjdCA9IGMoImNvdW50eSIsICJmaXBzIiwgInRydW1wX3ZvdGVzIiwgInRydW1wX3BjdCIpKQoKbmFtZXMoaGMpWzZdIDwtICJoaWxsYXJ5X3ZvdGVzIgpuYW1lcyhoYylbOV0gPC0gImhpbGxhcnlfcGN0IgoKZGYkaGlsbGFyeV92b3RlcyA8LSBoYyRoaWxsYXJ5X3ZvdGVzCmRmJGhpbGxhcnlfcGN0IDwtIGhjJGhpbGxhcnlfcGN0CmRmJHRvdGFsX3ZvdGVzIDwtIGhjJHRvdGFsX3ZvdGVzCgpkZiR0cnVtcF9tYXJnaW4gPC0gZGYkdHJ1bXBfdm90ZXMgLSBkZiRoaWxsYXJ5X3ZvdGVzCgojIEFkZHMgd2lubmVyIGNvbHVtbiB0byBkYXRhIGZyYW1lLgpkZiA8LSB0cmFuc2Zvcm0oZGYsIHByZXNfd2lubmVyID0gaWZlbHNlKGRmJGhpbGxhcnlfcGN0ID4gZGYkdHJ1bXBfcGN0LCAiQ2xpbnRvbiIsICJUcnVtcCIpKQoKdXNtYXAgPC0gYXBwZW5kX2RhdGEodXNtYXAsIGRmLCBrZXkuc2hwID0gImZpcHMiLCBrZXkuZGF0YSA9ICJmaXBzIikKYGBgCgojTWFwIENyZWF0aW9uCmBgYHtyfQojIEZpbmRpbmcgdGhlIG1peCBhbmQgbWF4IGtlZXAgY29sb3Igc2NhbGluZyBmYWlyIGJldHdlZW4gY2FuZGlkYXRlcy4KbWluIDwtIG1pbihjKHVzbWFwJHRydW1wX3BjdCwgdXNtYXAkaGlsbGFyeV9wY3QpKQptYXggPC0gbWF4KGModXNtYXAkdHJ1bXBfcGN0LCB1c21hcCRoaWxsYXJ5X3BjdCkpCgojIENyZWF0aW5nIGNvbG9yIHBhbGV0dGVzCmdvcF9wYWxldHRlIDwtIGNvbG9yTnVtZXJpYyhwYWxldHRlID0gIkJsdWVzIiwgZG9tYWluPWMobWluLCBtYXgpKQpkZW1fcGFsZXR0ZSA8LSBjb2xvck51bWVyaWMocGFsZXR0ZSA9ICJSZWRzIiwgZG9tYWluID0gYyhtaW4sIG1heCkpCndpbm5lcl9wYWxldHRlIDwtIGNvbG9yRmFjdG9yKGMoIkJsdWUiLCJSZWQiICksIGRvbWFpbiA9IHVzbWFwJHByZXNfd2lubmVyKQoKIyBQb3AtdXAgd2luZG93IGZvciB3aGVuIHlvdSBjbGljayBvbiBhIGNvdW50eS4KdXNwb3B1cCA8LSBwYXN0ZSgiQ291bnR5OiAiLCB1c21hcCRjb3VudHksICI8YnI+IiwKIldpbm5lcjogIiwgdXNtYXAkcHJlc193aW5uZXIsICI8YnI+IiwKIlRydW1wOiAiLCBwZXJjZW50KHVzbWFwJHRydW1wX3BjdCksICI8YnI+IiwKIkNsaW50b246ICIsIHBlcmNlbnQodXNtYXAkaGlsbGFyeV9wY3QpLCAiPGJyPiIsCiJNYXJnaW46ICIsIHVzbWFwJHRydW1wX21hcmdpbiwgIiB2b3Rlcy4iKQpgYGAKCgpgYGB7cn0KdXNtYXAgPC0gc2Y6OnN0X3RyYW5zZm9ybSh1c21hcCwgIitwcm9qPWxvbmdsYXQgK2RhdHVtPVdHUzg0IikKCiMgQnVpbGRpbmcgdGhlIG1hcCEKCndpZGdldCA8LSBsZWFmbGV0KHVzbWFwKSAlPiUKICBhZGRQcm92aWRlclRpbGVzKCJDYXJ0b0RCLlBvc2l0cm9uIikgJT4lCiAgYWRkUG9seWdvbnMoc3Ryb2tlID0gVFJVRSwKICAgICAgICAgICAgICB3ZWlnaHQgPSAxLAogICAgICAgICAgICAgIHNtb290aEZhY3RvciA9IDAuMiwKICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IC43NSwKICAgICAgICAgICAgICBwb3B1cCA9IHVzcG9wdXAsCiAgICAgICAgICAgICAgY29sb3IgPSB+d2lubmVyX3BhbGV0dGUodXNtYXAkcHJlc193aW5uZXIpLAogICAgICAgICAgICAgIGdyb3VwID0iV2lubmVycyIKICkgJT4lCiAgICBhZGRMZWdlbmQocG9zaXRpb24gPSAiYm90dG9tbGVmdCIsIGNvbG9ycyA9IGMoIiMzMzMzRkYiLCAiI0NEMzcwMCIpLCBsYWJlbHMgPSBjKCJDbGludG9uIiwgIlRydW1wIikpICU+JQoKICBhZGRQb2x5Z29ucyhzdHJva2UgPSBUUlVFLAogICAgICAgd2VpZ2h0ID0gMSwKICAgICAgIHNtb290aEZhY3RvciA9IDAuMiwgCiAgICAgICBmaWxsT3BhY2l0eSA9IC43NSwgCiAgICAgICBwb3B1cCA9IHVzcG9wdXAsIAogICAgICAgY29sb3IgPSB+ZGVtX3BhbGV0dGUodXNtYXAkdHJ1bXBfcGN0KSwKICAgICAgIGdyb3VwID0iVHJ1bXAiCiAgICAgICkgJT4lCgogIGFkZFBvbHlnb25zKHN0cm9rZSA9IFRSVUUsCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMSwKICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjIsIAogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gLjc1LCAKICAgICAgICAgICAgICBwb3B1cCA9IHVzcG9wdXAsIAogICAgICAgICAgICAgIGNvbG9yID0gfmdvcF9wYWxldHRlKHVzbWFwJGhpbGxhcnlfcGN0KSwKICAgICAgICAgICAgICBncm91cCA9ICJDbGludG9uIgogICkgJT4lCiAgCiAgYWRkTGF5ZXJzQ29udHJvbCgKICAgICAgYmFzZUdyb3Vwcz1jKCJXaW5uZXJzIiwgIlRydW1wIiwgIkNsaW50b24iKSwgIyAiQ29sbGVnZSBkZWdzIiAiT3RoZXIiCiAgICAgIHBvc2l0aW9uID0gImJvdHRvbWxlZnQiLAogICAgICBvcHRpb25zID0gbGF5ZXJzQ29udHJvbE9wdGlvbnMoY29sbGFwc2VkID0gRkFMU0UpCiAgICAgICkgCgp3aWRnZXQKYGBgCgpgYGB7cn0KI3NhdmVXaWRnZXQod2lkZ2V0LCBmaWxlID0gImVsZWN0aW9uX21hcC5odG1sIikKYGBgCgpgYGB7cn0KIyBUaGlzIHdpbGwgZXZlbnR1YWxseSBzaG93IGEgZ3JhZGllbnQgYWNyb3NzIGNvdW50aWVzIHVzaW5nIG1hcmdpbmFsIHZvdGVzLiAKCiN0ZXN0UGFsZXR0ZSA8LSBjb2xvclJhbXBQYWxldHRlKGMoIkJsdWUiLCJXaGl0ZSIsIlJlZCIgKSkKCiMgcGFsRGF0YSA8LSBjbGFzc0ludGVydmFscyh1c21hcCR0cnVtcF9tYXJnaW4sIHN0eWxlPSJxdWFudGlsZSIpCiMgdXNtYXAkY29sb3JzIDwtIGZpbmRDb2xvdXJzKHBhbERhdGEsIHdpbm5lclBhbGV0dGUoMTAwKSkKIyAKIyBsZWFmbGV0KHVzbWFwKSAlPiUKIyAgIGFkZFByb3ZpZGVyVGlsZXMoIkNhcnRvREIuUG9zaXRyb24iKSAlPiUKIyAgIGFkZFBvbHlnb25zKHN0cm9rZT1UUlVFLAojICAgICAgICAgICAgICAgd2VpZ2h0PTEsCiMgICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjIsCiMgICAgICAgICAgICAgICBmaWxsT3BhY2l0eSA9IC43NSwKIyAgICAgICAgICAgICAgIHBvcHVwID0gdXNwb3B1cCwKIyAgICAgICAgICAgICAgIGNvbG9yID0gfmNvbG9ycywKIyAgICAgICAgICAgICAgIGdyb3VwID0iV2lubmVycyIKIyAgKSAlPiUKIyAgICAgYWRkTGVnZW5kKHBvc2l0aW9uPSJib3R0b21sZWZ0IiwgY29sb3JzPWMoIiMzMzMzRkYiLCAiI0NEMzcwMCIpLCBsYWJlbHM9YygiQ2xpbnRvbiIsICJUcnVtcCIpKQpgYGAK